package com.cjie.ecommerce.service.impl;

import com.cjie.ecommerce.dao.ProductRepository;
import com.cjie.ecommerce.entity.Product;
import com.cjie.ecommerce.service.ProductService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Service
public class ProductServiceImpl implements ProductService {

    private static final Logger logger = LoggerFactory.getLogger(ProductServiceImpl.class);

    @Resource
    ProductRepository productRepository;
    // Redis中商品列表的key
    private static final String PRODUCT_LIST_KEY = "product:list";
    // Redis中商品详情的key前缀
    private static final String PRODUCT_DETAIL_KEY_PREFIX = "product:detail:";
    // 缓存过期时间（单位：分钟）
    private static final long CACHE_EXPIRE_MINUTES = 30;

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    // 这里应该是MyBatis的Mapper，为了示例简化直接模拟数据
    // @Autowired
    // private ProductMapper productMapper;

    @Override
    public List<Product> getAllProducts() {
        logger.info("尝试从Redis获取商品列表缓存");

        // 1. 先尝试从Redis获取缓存
        List<Product> productList = (List<Product>) redisTemplate.opsForValue().get(PRODUCT_LIST_KEY);

        if (!CollectionUtils.isEmpty(productList)) {
            logger.info("从Redis缓存中获取商品列表成功，商品数量：{}", productList.size());
            return productList;
        }

        logger.info("Redis中没有商品列表缓存，将从数据库查询");

        // 2. 缓存中没有，从数据库查询
        // 这里模拟从数据库查询
        productList = productRepository.mockProductsFromDB();
        // 实际项目中应该是：
        // productList = productMapper.selectAll();

        if (!CollectionUtils.isEmpty(productList)) {
            logger.info("从数据库查询到商品列表，商品数量：{}，将存入Redis缓存", productList.size());

            // 3. 将查询结果存入Redis，并设置过期时间
            redisTemplate.opsForValue().set(
                    PRODUCT_LIST_KEY,
                    productList,
                    CACHE_EXPIRE_MINUTES,
                    TimeUnit.MINUTES
            );
        }

        return productList;
    }

    /**
     * 异常处理建议:
     * 在Service层添加降级逻辑。
     * @param id
     * @return
     */
    public Product getProduct2(Long id) {
        try {
            // 先查Redis
            Product product = (Product) redisTemplate.opsForValue().get("product:" + id);
            if (product != null) {
                return product;
            }
            // 再查数据库...
            //return productMapper.selectById(id);
            return null;
        } catch (Exception e) {
            logger.error("Redis访问异常，降级查数据库", e);
            // 直接查询数据库
            //return productMapper.selectById(id);
            return null;
        }
    }

    @Override
    public Product getProductById(Long id) {
        if (id == null) {
            return null;
        }

        String cacheKey = PRODUCT_DETAIL_KEY_PREFIX + id;
        logger.info("尝试从Redis获取商品详情缓存，key={}", cacheKey);

        // 1. 先尝试从Redis获取缓存
        Product product = (Product) redisTemplate.opsForValue().get(cacheKey);

        if (product != null) {
            logger.info("从Redis缓存中获取商品详情成功，商品ID：{}", id);
            return product;
        }

        logger.info("Redis中没有商品ID={}的缓存，将从数据库查询", id);

        // 2. 缓存中没有，从数据库查询
        // 这里模拟从数据库查询
        product = productRepository.mockProductFromDB(id);
        // 实际项目中应该是：
        // product = productMapper.selectById(id);

        if (product != null) {
            logger.info("从数据库查询到商品详情，商品ID：{}，将存入Redis缓存", id);

            // 3. 将查询结果存入Redis，并设置过期时间
            redisTemplate.opsForValue().set(
                    cacheKey,
                    product,
                    CACHE_EXPIRE_MINUTES,
                    TimeUnit.MINUTES
            );
        }

        return product;
    }

    @Override
    public void updateProduct(Product product) {
        if (product == null || product.getId() == null) {
            return;
        }

        logger.info("更新商品信息，商品ID：{}", product.getId());

        // 1. 更新数据库
        // 这里省略实际数据库更新操作
        // productMapper.updateById(product);

        // 2. 更新缓存
        String cacheKey = PRODUCT_DETAIL_KEY_PREFIX + product.getId();
        redisTemplate.opsForValue().set(
                cacheKey,
                product,
                CACHE_EXPIRE_MINUTES,
                TimeUnit.MINUTES
        );
        logger.info("更新商品ID={}的Redis缓存", product.getId());

        // 3. 使商品列表缓存失效（因为列表可能包含该商品的信息）
        redisTemplate.delete(PRODUCT_LIST_KEY);
        logger.info("删除商品列表缓存，等待下次查询时重新加载");
    }

    @Override
    public void deleteProduct(Long id) {
        if (id == null) {
            return;
        }

        logger.info("删除商品，商品ID：{}", id);

        // 1. 删除数据库记录
        // 这里省略实际数据库删除操作
        // productMapper.deleteById(id);

        // 2. 删除缓存
        String cacheKey = PRODUCT_DETAIL_KEY_PREFIX + id;
        redisTemplate.delete(cacheKey);
        logger.info("删除商品ID={}的Redis缓存", id);

        // 3. 使商品列表缓存失效
        redisTemplate.delete(PRODUCT_LIST_KEY);
        logger.info("删除商品列表缓存，等待下次查询时重新加载");
    }
}